<?php
/**
 * Created by sublime 3.
 * Auth: Inhere
 * Date: 14-
 * Time: 10:35
 * Uesd: 主要功能是 hi
 */
namespace ulue\core\view;

use Debug;
use ulue\core\utils;
use ulue\core\abstracts\AbstractCore;

abstract class AbstractWidget extends AbstractCore implements InterfaceWidget
{
    static protected $box = [];

    public function __construct()
    {
        // $this->basePath = __DIR__;
        $this->init();
    }

    protected function init()
    {}

    protected function beforeExecute()
    {
        return true;
    }

    /**
     * @return null
     */
    public function execute()
    {
        $result = null;

        \Debug::trace('execute widget '.get_class($this));

        if ( $this->beforeExecute() ) {

            $result = $this->beginExecute();

            $this->afterExecute($result);
        }

        return $result;
    }

    abstract protected function beginExecute();

    protected function afterExecute(&$result)
    {

    }

    /**
     * @param $view
     * @param array $data
     * @return string
     */
    public function display($view, array $data=[])
    {
        $viewFile  = $this->getWidgetViewFile($view);

        return $this->getBufferOutputStream($viewFile, $data);
    }

    /**
     * @param $view
     * @param array $data
     * @return string
     */
    public function render($view, array $data=[])
    {
        return $this->display($view,$data);
    }

    static public function start(array $conf=[])
    {
        $config['class'] = get_called_class();
        $config['attrs'] = $conf;

        $widget = utils\Invoker::object($config);

        return (self::$box[] = $widget);
    }

    static public function widget(array $conf=[])
    {
        $config['class'] = get_called_class();
        $config['attrs'] = $conf;

        $widget = utils\Invoker::object($config);

        return $widget->execute();
    }

    static public function end()
    {
        if (self::$box) {
            $widget = array_pop(self::$box);

            if ( get_class($widget) === get_called_class() ) {
                echo $widget->execute();

                return $widget;
            } else {
                throw new \DRuntimeException("Error Processing Request");
            }

        } else {
            throw new \DLogicException('Please run the class methods '.get_called_class().'::start(), before calling.');
        }
    }

    /**
     * @param  array $varData
     * @return $this
     */
    public function load(array $varData=[])
    {
        if ($varData) {
            foreach ($varData as $name => $value) {
                $name && $this->$name = $value;
            }
        }

        $this->init();

        return $this;
    }

    // html file
    /**
     * @param $name
     * @return string
     */
    public function getWidgetViewFile($name)
    {
        if (!$name) {
            \Trigger::error('请传入要加载的视图');
        }

        $name  = trim($name);

        # 使用别名 @module @run @app @web
        if ( substr($name, 0,1)==='@' ) {
            $file = rtrim(\Ulue::resolveAlias($name),'/').'.html';
        } else {
            $class = new \ReflectionClass($this);

            $path  = dirname($class->getFileName()) . '\views';

            // widgets dir path
            // $class = strstr(get_class($this),'\widgets\\',true).'\widgets\views';
            // $path  = \Ulue::resolveNamespace( $class );

            if ( substr($path, 0,1)==='@' ) {
                $file = rtrim(\Ulue::resolveAlias($path),'/')."/$name.html";
            } else {
                $file  = $path."/$name.html";
            }


        }

        if (!file_exists($file)) {
            \Trigger::error("要加载的视图文件 $file 不存在!");
        }

        return $file;
    }

    /**
     * 加载视图文件，解析传入视图的变量
     * @param  string $viewFile
     * @param  array  $viewVars
     * @return string
     */
    public function getBufferOutputStream($viewFile, array $viewVars)
    {
        Debug::trace('i 准备开启缓冲区加载解析视图，获取视图数据。',"@param \$viewFile = {$viewFile}");

        #  打开输出控制缓冲
        ob_start();
        ob_implicit_flush(false);

        if ($viewVars) {
            @extract($viewVars, EXTR_PREFIX_SAME, 'data_');
        }

        require $viewFile;


        $content = ob_get_clean();      #  获取缓冲区的内容

        return $content;
    }

    /**
     * @return AbstractView
     */
    public function getView()
    {
        return \Ulue::$app->getView();
    }

    /**
     * @return \ulue\core\controller\AbstractWebController
     */
    public function getController()
    {
        return \Ulue::$app->getController();
    }

}